#include "iworld_level.h"
#include "iworld_loader.h"
#include "debug/logger.h"
#include "misc/strutil.h"

namespace renderit
{
	namespace messiah
	{
		bool iworld_level::load(iworld_loader * w, tinyxml2::XMLElement * Level_root_elem)
		{
			iworld_loader_ = w;
			Level_elem_ = Level_root_elem->FirstChildElementMultiLevel("Root/Entity");
			if (!Level_elem_)
			{
				logger::warn("Load Level Failed, Miss Root/Entity! iWorld:%s", iworld_loader_->name_.c_str());
				return false;
			}
			const char * name = Level_elem_->GetChildText("Name", nullptr);
			if (!name)
			{
				logger::warn("Load Level Failed, Missing Name! iWorld:%s", iworld_loader_->name_.c_str());
				return false;
			}

			name_ = name;

			Entities_elem_ = Level_elem_->FirstChildElementMultiLevel("RootArea/Root/Entity/Entities");
			if (!Entities_elem_)
			{
				logger::warn("Load Level Failed, Missing Entities! iWorld:%s!", iworld_loader_->name_.c_str());
				return false;
			}

			xml_entities_ = Entities_elem_->ChildrenElements("Item");

			logger::info("Load Level Success! Name:%s, Entities Count:%d", name_.c_str(), xml_entities_.size());

			return find_components();
		}

		bool iworld_level::find_components()
		{
			for (auto& Entity_root_elem : xml_entities_)
			{
				tinyxml2::XMLElement * Entity = Entity_root_elem->FirstChildElementMultiLevel("Root/Entity");
				if (!Entity)
				{
					logger::warn("Failed To Get Entity From Item! iWorld:%s", iworld_loader_->name_.c_str());
					return false;
				}

				if (!find_component_in_entity(Entity))
				{
					return false;
				}
			}

			return true;
		}

		bool iworld_level::find_component_in_entity(tinyxml2::XMLElement * Entity_root_elem)
		{
			find_component_in_path(Entity_root_elem, "");
			
			return true;
		}

		bool iworld_level::find_component_in_path(tinyxml2::XMLElement * root_elem, const std::string& path)
		{
			const char * type = root_elem->Attribute("type");
			if (type && strutil::str_endswith(type, "Component"))
			{
				path_info i;
				i.name = type;
				i.path = path;
				component_path_[i]++;
			}

			const char * text = root_elem->GetText();
			if (text && strutil::str_is_guid(text))
			{
				path_info i;
				i.name = "";
				i.path = path;
				guid_path_[i] ++;

				guid_info gi;
				gi.guid = text;
				gi.path = path;
				gi.xml_elem_ = root_elem;
				xml_guid_map_[gi.guid].push_back(gi);
			}

			tinyxml2::XMLElement * first_child = root_elem->FirstChildElement(nullptr);
			while (first_child)
			{
				find_component_in_path(first_child, path.length() > 0 ? path + "." + first_child->Value() : path + first_child->Value());
				first_child = first_child->NextSiblingElement();
			}

			return true;
		}
	}
}